home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / Mesa-2.2 / src-aux / shapes.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-25  |  27.1 KB  |  1,062 lines

  1. /* shapes.c */
  2.  
  3.  
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <math.h>
  7. #include <GL/gl.h>
  8. #include <GL/glu.h>
  9. #include "glaux.h"
  10. #include "3d.h"
  11.  
  12.  
  13.  
  14. #define SPHEREWIRE    0
  15. #define CUBEWIRE    1
  16. #define BOXWIRE        2
  17. #define TORUSWIRE    3
  18. #define CYLINDERWIRE    4
  19. #define ICOSAWIRE    5
  20. #define OCTAWIRE    6
  21. #define TETRAWIRE    7
  22. #define DODECAWIRE    8
  23. #define CONEWIRE    9
  24. #define SPHERESOLID    10
  25. #define CUBESOLID    11
  26. #define BOXSOLID    12
  27. #define TORUSSOLID    13
  28. #define CYLINDERSOLID    14
  29. #define ICOSASOLID    15
  30. #define OCTASOLID    16
  31. #define TETRASOLID    17
  32. #define DODECASOLID    18
  33. #define CONESOLID    19
  34.  
  35. #ifndef PI
  36. #define PI 3.1415926535897
  37. #endif
  38.  
  39.  
  40. /*    structure for each geometric object    */
  41. typedef struct model {
  42.     GLuint list;    /*  display list to render object   */
  43.     struct model *ptr;    /*  pointer to next object    */
  44.     int numParam;    /*  # of parameters        */
  45.     GLdouble *params;    /*  array with parameters    */
  46. } MODEL, *MODELPTR;
  47.  
  48. /*    array of linked lists--used to keep track of display lists 
  49.  *    for each different type of geometric object.
  50.  */
  51. static MODELPTR lists[25] = {
  52.     NULL, NULL, NULL, NULL, NULL,
  53.     NULL, NULL, NULL, NULL, NULL,
  54.     NULL, NULL, NULL, NULL, NULL,
  55.     NULL, NULL, NULL, NULL, NULL,
  56.     NULL, NULL, NULL, NULL, NULL
  57. };
  58.  
  59. GLuint findList (int lindex, GLdouble *paramArray, int size);
  60. int compareParams (GLdouble *oneArray, GLdouble *twoArray, int size);
  61. GLuint makeModelPtr (int lindex, GLdouble *sizeArray, int count);
  62.  
  63. static void drawbox(GLdouble, GLdouble, GLdouble, 
  64.     GLdouble, GLdouble, GLdouble, GLenum);
  65. static void doughnut(GLdouble, GLdouble, GLint, GLint, GLenum);
  66. static void icosahedron(GLdouble *, GLdouble, GLenum);
  67. static void octahedron(GLdouble *, GLdouble, GLenum);
  68. static void tetrahedron(GLdouble *, GLdouble, GLenum);
  69. static void subdivide(int, GLdouble *, GLdouble *, GLdouble *,
  70.     GLdouble *, GLdouble, GLenum, int);
  71. static void drawtriangle(int, int, int,
  72.     GLdouble *, GLdouble, GLenum, int);
  73. static void recorditem(GLdouble *, GLdouble *, GLdouble *,
  74.     GLdouble *, GLdouble, GLenum, int);
  75. static void initdodec(void);
  76. static void dodecahedron(GLdouble *, GLdouble, GLenum);
  77. static void pentagon(int, int, int, int, int, GLenum);
  78.  
  79.  
  80. /*  Render wire frame or solid sphere.  If no display list with
  81.  *  the current model size exists, create a new display list.
  82.  */
  83. void auxWireSphere (GLdouble radius)
  84. {
  85.     GLUquadricObj *quadObj;
  86.     GLdouble *sizeArray;
  87.     GLuint displayList;
  88.  
  89.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  90.     *sizeArray = radius;
  91.     displayList = findList (SPHEREWIRE, sizeArray, 1);
  92.  
  93.     if (displayList == 0) {
  94.     glNewList(makeModelPtr (SPHEREWIRE, sizeArray, 1),
  95.         GL_COMPILE_AND_EXECUTE);
  96.         quadObj = gluNewQuadric ();
  97.         gluQuadricDrawStyle (quadObj, GLU_LINE);
  98.         gluSphere (quadObj, radius, 16, 16);
  99.     glEndList();
  100.     }
  101.     else {
  102.     glCallList(displayList);
  103.     free (sizeArray);
  104.     }
  105. }
  106.  
  107. void auxSolidSphere (GLdouble radius)
  108. {
  109.     GLUquadricObj *quadObj;
  110.     GLdouble *sizeArray;
  111.     GLuint displayList;
  112.  
  113.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  114.     *sizeArray = radius;
  115.     displayList = findList (SPHERESOLID, sizeArray, 1);
  116.  
  117.     if (displayList == 0) {
  118.     glNewList(makeModelPtr (SPHERESOLID, sizeArray, 1),
  119.         GL_COMPILE_AND_EXECUTE);
  120.         quadObj = gluNewQuadric ();
  121.         gluQuadricDrawStyle (quadObj, GLU_FILL);
  122.         gluQuadricNormals (quadObj, GLU_SMOOTH);
  123.         gluSphere (quadObj, radius, 16, 16);
  124.     glEndList();
  125.     }
  126.     else {
  127.     glCallList(displayList);
  128.     free (sizeArray);
  129.     }
  130. }
  131.  
  132. /*  Render wire frame or solid cube.  If no display list with
  133.  *  the current model size exists, create a new display list.
  134.  */
  135. void auxWireCube (GLdouble size)
  136. {
  137.     GLdouble *sizeArray;
  138.     GLuint displayList;
  139.  
  140.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  141.     *sizeArray = size;
  142.     displayList = findList (CUBEWIRE, sizeArray, 1);
  143.  
  144.     if (displayList == 0) {
  145.     glNewList(makeModelPtr (CUBEWIRE, sizeArray, 1),
  146.         GL_COMPILE_AND_EXECUTE);
  147.         drawbox(-size/2., size/2., -size/2., size/2., 
  148.         -size/2., size/2., GL_LINE_LOOP);
  149.     glEndList();
  150.     }
  151.     else {
  152.     glCallList(displayList);
  153.     free (sizeArray);
  154.     }
  155. }
  156.  
  157. void auxSolidCube (GLdouble size)
  158. {
  159.     GLdouble *sizeArray;
  160.     GLuint displayList;
  161.  
  162.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  163.     *sizeArray = size;
  164.     displayList = findList (CUBESOLID, sizeArray, 1);
  165.  
  166.     if (displayList == 0) {
  167.     glNewList(makeModelPtr (CUBESOLID, sizeArray, 1),
  168.         GL_COMPILE_AND_EXECUTE);
  169.         drawbox(-size/2., size/2., -size/2., size/2., 
  170.         -size/2., size/2., GL_QUADS);
  171.     glEndList();
  172.     }
  173.     else {
  174.     glCallList(displayList);
  175.     free (sizeArray);
  176.     }
  177. }
  178.  
  179. /*  Render wire frame or solid cube.  If no display list with
  180.  *  the current model size exists, create a new display list.
  181.  */
  182. void auxWireBox (GLdouble width, GLdouble height, GLdouble depth)
  183. {
  184.     GLdouble *sizeArray, *tmp;
  185.     GLuint displayList;
  186.  
  187.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 3);
  188.     tmp = sizeArray;
  189.     *tmp++ = width;
  190.     *tmp++ = height;
  191.     *tmp++ = depth;
  192.     displayList = findList (BOXWIRE, sizeArray, 3);
  193.  
  194.     if (displayList == 0) {
  195.     glNewList(makeModelPtr (BOXWIRE, sizeArray, 3),
  196.         GL_COMPILE_AND_EXECUTE);
  197.         drawbox(-width/2., width/2., -height/2., height/2., 
  198.         -depth/2., depth/2., GL_LINE_LOOP);
  199.     glEndList();
  200.     }
  201.     else {
  202.     glCallList(displayList);
  203.     free (sizeArray);
  204.     }
  205. }
  206.  
  207. void auxSolidBox (GLdouble width, GLdouble height, GLdouble depth)
  208. {
  209.     GLdouble *sizeArray, *tmp;
  210.     GLuint displayList;
  211.  
  212.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 3);
  213.     tmp = sizeArray;
  214.     *tmp++ = width;
  215.     *tmp++ = height;
  216.     *tmp++ = depth;
  217.     displayList = findList (BOXSOLID, sizeArray, 3);
  218.  
  219.     if (displayList == 0) {
  220.     glNewList(makeModelPtr (BOXSOLID, sizeArray, 3),
  221.         GL_COMPILE_AND_EXECUTE);
  222.         drawbox(-width/2., width/2., -height/2., height/2., 
  223.         -depth/2., depth/2., GL_QUADS);
  224.     glEndList();
  225.     }
  226.     else {
  227.     glCallList(displayList);
  228.     free (sizeArray);
  229.     }
  230. }
  231.  
  232. /*  Render wire frame or solid tori.  If no display list with
  233.  *  the current model size exists, create a new display list.
  234.  */
  235. void auxWireTorus (GLdouble innerRadius, GLdouble outerRadius)
  236. {
  237.     GLdouble *sizeArray, *tmp;
  238.     GLuint displayList;
  239.  
  240.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  241.     tmp = sizeArray;
  242.     *tmp++ = innerRadius;
  243.     *tmp++ = outerRadius;
  244.     displayList = findList (TORUSWIRE, sizeArray, 2);
  245.  
  246.     if (displayList == 0) {
  247.     glNewList(makeModelPtr (TORUSWIRE, sizeArray, 2),
  248.         GL_COMPILE_AND_EXECUTE);
  249.         doughnut(innerRadius, outerRadius, 5, 10, GL_LINE_LOOP);
  250.     glEndList();
  251.     }
  252.     else {
  253.     glCallList(displayList);
  254.     free (sizeArray);
  255.     }
  256. }
  257.  
  258. void auxSolidTorus (GLdouble innerRadius, GLdouble outerRadius)
  259. {
  260.     GLdouble *sizeArray, *tmp;
  261.     GLuint displayList;
  262.  
  263.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  264.     tmp = sizeArray;
  265.     *tmp++ = innerRadius;
  266.     *tmp++ = outerRadius;
  267.     displayList = findList (TORUSSOLID, sizeArray, 2);
  268.  
  269.     if (displayList == 0) {
  270.     glNewList(makeModelPtr (TORUSSOLID, sizeArray, 2),
  271.         GL_COMPILE_AND_EXECUTE);
  272.         doughnut(innerRadius, outerRadius, 8, 15, GL_QUADS);
  273.     glEndList();
  274.     }
  275.     else {
  276.     glCallList(displayList);
  277.     free (sizeArray);
  278.     }
  279. }
  280.  
  281. /*  Render wire frame or solid cylinders.  If no display list with
  282.  *  the current model size exists, create a new display list.
  283.  */
  284. void auxWireCylinder (GLdouble radius, GLdouble height)
  285. {
  286.     GLUquadricObj *quadObj;
  287.     GLdouble *sizeArray, *tmp;
  288.     GLuint displayList;
  289.  
  290.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  291.     tmp = sizeArray;
  292.     *tmp++ = radius;
  293.     *tmp++ = height;
  294.     displayList = findList (CYLINDERWIRE, sizeArray, 2);
  295.  
  296.     if (displayList == 0) {
  297.     glNewList(makeModelPtr (CYLINDERWIRE, sizeArray, 2),
  298.         GL_COMPILE_AND_EXECUTE);
  299.         glPushMatrix ();
  300.         glRotatef (90.0, 1.0, 0.0, 0.0);
  301.         glTranslatef (0.0, 0.0, -1.0);
  302.         quadObj = gluNewQuadric ();
  303.         gluQuadricDrawStyle (quadObj, GLU_LINE);
  304.         gluCylinder (quadObj, radius, radius, height, 12, 2);
  305.         glPopMatrix ();
  306.     glEndList();
  307.     }
  308.     else {
  309.     glCallList(displayList);
  310.     free (sizeArray);
  311.     }
  312. }
  313.  
  314. void auxSolidCylinder (GLdouble radius, GLdouble height)
  315. {
  316.     GLUquadricObj *quadObj;
  317.     GLdouble *sizeArray, *tmp;
  318.     GLuint displayList;
  319.  
  320.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  321.     tmp = sizeArray;
  322.     *tmp++ = radius;
  323.     *tmp++ = height;
  324.     displayList = findList (CYLINDERSOLID, sizeArray, 2);
  325.  
  326.     if (displayList == 0) {
  327.     glNewList(makeModelPtr (CYLINDERSOLID, sizeArray, 2),
  328.         GL_COMPILE_AND_EXECUTE);
  329.         glPushMatrix ();
  330.         glRotatef (90.0, 1.0, 0.0, 0.0);
  331.         glTranslatef (0.0, 0.0, -1.0);
  332.         quadObj = gluNewQuadric ();
  333.         gluQuadricDrawStyle (quadObj, GLU_FILL);
  334.         gluQuadricNormals (quadObj, GLU_SMOOTH);
  335.         gluCylinder (quadObj, radius, radius, height, 12, 2);
  336.         glPopMatrix ();
  337.     glEndList();
  338.     }
  339.     else {
  340.     glCallList(displayList);
  341.     free (sizeArray);
  342.     }
  343. }
  344.  
  345. /*  Render wire frame or solid icosahedra.  If no display list with
  346.  *  the current model size exists, create a new display list.
  347.  */
  348. void auxWireIcosahedron (GLdouble radius)
  349. {
  350.     GLdouble *sizeArray;
  351.     GLuint displayList;
  352.     static GLdouble center[3] = {0.0, 0.0, 0.0};
  353.  
  354.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  355.     *sizeArray = radius;
  356.     displayList = findList (ICOSAWIRE, sizeArray, 1);
  357.  
  358.     if (displayList == 0) {
  359.     glNewList(makeModelPtr (ICOSAWIRE, sizeArray, 1),
  360.         GL_COMPILE_AND_EXECUTE);
  361.         icosahedron (center, radius, GL_LINE_LOOP);
  362.     glEndList();
  363.     }
  364.     else {
  365.     glCallList(displayList);
  366.     free (sizeArray);
  367.     }
  368. }
  369.  
  370. void auxSolidIcosahedron (GLdouble radius)
  371. {
  372.     GLdouble *sizeArray;
  373.     GLuint displayList;
  374.     static GLdouble center[3] = {0.0, 0.0, 0.0};
  375.  
  376.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  377.     *sizeArray = radius;
  378.     displayList = findList (ICOSASOLID, sizeArray, 1);
  379.  
  380.     if (displayList == 0) {
  381.     glNewList(makeModelPtr (ICOSASOLID, sizeArray, 1),
  382.         GL_COMPILE_AND_EXECUTE);
  383.         icosahedron (center, radius, GL_TRIANGLES);
  384.     glEndList();
  385.     }
  386.     else {
  387.     glCallList(displayList);
  388.     free (sizeArray);
  389.     }
  390. }
  391.  
  392. /*  Render wire frame or solid octahedra.  If no display list with
  393.  *  the current model size exists, create a new display list.
  394.  */
  395. void auxWireOctahedron (GLdouble radius)
  396. {
  397.     GLdouble *sizeArray;
  398.     GLuint displayList;
  399.     static GLdouble center[3] = {0.0, 0.0, 0.0};
  400.  
  401.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  402.     *sizeArray = radius;
  403.     displayList = findList (OCTAWIRE, sizeArray, 1);
  404.  
  405.     if (displayList == 0) {
  406.     glNewList(makeModelPtr (OCTAWIRE, sizeArray, 1),
  407.         GL_COMPILE_AND_EXECUTE);
  408.         octahedron (center, radius, GL_LINE_LOOP);
  409.     glEndList();
  410.     }
  411.     else {
  412.     glCallList(displayList);
  413.     free (sizeArray);
  414.     }
  415. }
  416.  
  417. void auxSolidOctahedron (GLdouble radius)
  418. {
  419.     GLdouble *sizeArray;
  420.     GLuint displayList;
  421.     static GLdouble center[3] = {0.0, 0.0, 0.0};
  422.  
  423.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  424.     *sizeArray = radius;
  425.     displayList = findList (OCTASOLID, sizeArray, 1);
  426.  
  427.     if (displayList == 0) {
  428.     glNewList(makeModelPtr (OCTASOLID, sizeArray, 1),
  429.         GL_COMPILE_AND_EXECUTE);
  430.         octahedron (center, radius, GL_TRIANGLES);
  431.     glEndList();
  432.     }
  433.     else {
  434.     glCallList(displayList);
  435.     free (sizeArray);
  436.     }
  437. }
  438.  
  439. /*  Render wire frame or solid tetrahedra.  If no display list with
  440.  *  the current model size exists, create a new display list.
  441.  */
  442. void auxWireTetrahedron (GLdouble radius)
  443. {
  444.     GLdouble *sizeArray;
  445.     GLuint displayList;
  446.     static GLdouble center[3] = {0.0, 0.0, 0.0};
  447.  
  448.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  449.     *sizeArray = radius;
  450.     displayList = findList (TETRAWIRE, sizeArray, 1);
  451.  
  452.     if (displayList == 0) {
  453.     glNewList(makeModelPtr (TETRAWIRE, sizeArray, 1),
  454.         GL_COMPILE_AND_EXECUTE);
  455.         tetrahedron (center, radius, GL_LINE_LOOP);
  456.     glEndList();
  457.     }
  458.     else {
  459.     glCallList(displayList);
  460.     free (sizeArray);
  461.     }
  462. }
  463.  
  464. void auxSolidTetrahedron (GLdouble radius)
  465. {
  466.     GLdouble *sizeArray;
  467.     GLuint displayList;
  468.     static GLdouble center[3] = {0.0, 0.0, 0.0};
  469.  
  470.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  471.     *sizeArray = radius;
  472.     displayList = findList (TETRASOLID, sizeArray, 1);
  473.  
  474.     if (displayList == 0) {
  475.     glNewList(makeModelPtr (TETRASOLID, sizeArray, 1),
  476.         GL_COMPILE_AND_EXECUTE);
  477.         tetrahedron (center, radius, GL_TRIANGLES);
  478.     glEndList();
  479.     }
  480.     else {
  481.     glCallList(displayList);
  482.     free (sizeArray);
  483.     }
  484. }
  485.  
  486. /*  Render wire frame or solid dodecahedra.  If no display list with
  487.  *  the current model size exists, create a new display list.
  488.  */
  489. void auxWireDodecahedron (GLdouble radius)
  490. {
  491.     GLdouble *sizeArray;
  492.     GLuint displayList;
  493.     static GLdouble center[3] = {0.0, 0.0, 0.0};
  494.  
  495.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  496.     *sizeArray = radius;
  497.     displayList = findList (DODECAWIRE, sizeArray, 1);
  498.  
  499.     if (displayList == 0) {
  500.     glNewList(makeModelPtr (DODECAWIRE, sizeArray, 1),
  501.         GL_COMPILE_AND_EXECUTE);
  502.         dodecahedron (center, radius/1.73, GL_LINE_LOOP);
  503.     glEndList();
  504.     }
  505.     else {
  506.     glCallList(displayList);
  507.     free (sizeArray);
  508.     }
  509. }
  510.  
  511. void auxSolidDodecahedron (GLdouble radius)
  512. {
  513.     GLdouble *sizeArray;
  514.     GLuint displayList;
  515.     static GLdouble center[3] = {0.0, 0.0, 0.0};
  516.  
  517.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  518.     *sizeArray = radius;
  519.     displayList = findList (DODECASOLID, sizeArray, 1);
  520.  
  521.     if (displayList == 0) {
  522.     glNewList(makeModelPtr (DODECASOLID, sizeArray, 1),
  523.         GL_COMPILE_AND_EXECUTE);
  524.         dodecahedron (center, radius/1.73, GL_TRIANGLE_FAN);
  525.     glEndList();
  526.     }
  527.     else {
  528.     glCallList(displayList);
  529.     free (sizeArray);
  530.     }
  531. }
  532.  
  533. /*  Render wire frame or solid cones.  If no display list with
  534.  *  the current model size exists, create a new display list.
  535.  */
  536. void auxWireCone (GLdouble base, GLdouble height)
  537. {
  538.     GLUquadricObj *quadObj;
  539.     GLdouble *sizeArray, *tmp;
  540.     GLuint displayList;
  541.  
  542.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  543.     tmp = sizeArray;
  544.     *tmp++ = base;
  545.     *tmp++ = height;
  546.     displayList = findList (CONEWIRE, sizeArray, 2);
  547.  
  548.     if (displayList == 0) {
  549.     glNewList(makeModelPtr (CONEWIRE, sizeArray, 2),
  550.         GL_COMPILE_AND_EXECUTE);
  551.         quadObj = gluNewQuadric ();
  552.         gluQuadricDrawStyle (quadObj, GLU_LINE);
  553.         gluCylinder (quadObj, base, 0.0, height, 15, 10);
  554.     glEndList();
  555.     }
  556.     else {
  557.     glCallList(displayList);
  558.     free (sizeArray);
  559.     }
  560. }
  561.  
  562. void auxSolidCone (GLdouble base, GLdouble height)
  563. {
  564.     GLUquadricObj *quadObj;
  565.     GLdouble *sizeArray, *tmp;
  566.     GLuint displayList;
  567.  
  568.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  569.     tmp = sizeArray;
  570.     *tmp++ = base;
  571.     *tmp++ = height;
  572.     displayList = findList (CONEWIRE, sizeArray, 2);
  573.  
  574.     if (displayList == 0) {
  575.     glNewList(makeModelPtr (CONEWIRE, sizeArray, 2),
  576.         GL_COMPILE_AND_EXECUTE);
  577.         quadObj = gluNewQuadric ();
  578.         gluQuadricDrawStyle (quadObj, GLU_FILL);
  579.         gluQuadricNormals (quadObj, GLU_SMOOTH);
  580.         gluCylinder (quadObj, base, 0.0, height, 15, 10);
  581.     glEndList();
  582.     }
  583.     else {
  584.     glCallList(displayList);
  585.     free (sizeArray);
  586.     }
  587. }
  588.  
  589. /* Routines to build 3 dimensional solids, including:
  590.  *
  591.  * drawbox, doughnut, icosahedron, 
  592.  * octahedron, tetrahedron, dodecahedron.
  593.  */
  594.  
  595. /* drawbox:
  596.  *
  597.  * draws a rectangular box with the given x, y, and z ranges.  
  598.  * The box is axis-aligned.
  599.  */
  600. static void drawbox(GLdouble x0, GLdouble x1, GLdouble y0, GLdouble y1,
  601.     GLdouble z0, GLdouble z1, GLenum type)
  602. {
  603.     static GLdouble n[6][3] = {
  604.     {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0},
  605.     {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0}
  606.     };
  607.     static GLint faces[6][4] = {
  608.     { 0, 1, 2, 3 }, { 3, 2, 6, 7 }, { 7, 6, 5, 4 },
  609.     { 4, 5, 1, 0 }, { 5, 6, 2, 1 }, { 7, 4, 0, 3 }
  610.     };
  611.     GLdouble v[8][3], tmp;
  612.     GLint i;
  613.  
  614.     if (x0 > x1) {
  615.     tmp = x0; x0 = x1; x1 = tmp;
  616.     }
  617.     if (y0 > y1) {
  618.     tmp = y0; y0 = y1; y1 = tmp; 
  619.     }
  620.     if (z0 > z1) {
  621.     tmp = z0; z0 = z1; z1 = tmp; 
  622.     }
  623.     v[0][0] = v[1][0] = v[2][0] = v[3][0] = x0;
  624.     v[4][0] = v[5][0] = v[6][0] = v[7][0] = x1;
  625.     v[0][1] = v[1][1] = v[4][1] = v[5][1] = y0;
  626.     v[2][1] = v[3][1] = v[6][1] = v[7][1] = y1;
  627.     v[0][2] = v[3][2] = v[4][2] = v[7][2] = z0;
  628.     v[1][2] = v[2][2] = v[5][2] = v[6][2] = z1;
  629.  
  630.     for (i = 0; i < 6; i++) {
  631.     glBegin(type);
  632.     glNormal3dv(&n[i][0]);
  633.     glVertex3dv(&v[faces[i][0]][0]);
  634.     glNormal3dv(&n[i][0]);
  635.     glVertex3dv(&v[faces[i][1]][0]);
  636.     glNormal3dv(&n[i][0]);
  637.     glVertex3dv(&v[faces[i][2]][0]);
  638.     glNormal3dv(&n[i][0]);
  639.     glVertex3dv(&v[faces[i][3]][0]);
  640.     glEnd();
  641.     }
  642. }
  643.  
  644. /* doughnut:
  645.  *
  646.  * draws a doughnut, centered at (0, 0, 0) whose axis is aligned with
  647.  * the z-axis.  The doughnut's major radius is R, and minor radius is r.
  648.  */
  649.  
  650. static void doughnut(GLdouble r, GLdouble R, GLint nsides, GLint rings, GLenum type)
  651. {
  652.     int    i, j;
  653.     GLdouble    theta, phi, theta1, phi1;
  654.     GLdouble    p0[03], p1[3], p2[3], p3[3];
  655.     GLdouble    n0[3], n1[3], n2[3], n3[3];
  656.  
  657.     for (i = 0; i < rings; i++) {
  658.     theta = (GLdouble)i*2.0*PI/rings;
  659.     theta1 = (GLdouble)(i+1)*2.0*PI/rings;
  660.     for (j = 0; j < nsides; j++) {
  661.         phi = (GLdouble)j*2.0*PI/nsides;
  662.         phi1 = (GLdouble)(j+1)*2.0*PI/nsides;
  663.  
  664.         p0[0] = cos(theta)*(R + r*cos(phi));
  665.         p0[1] = -sin(theta)*(R + r*cos(phi));
  666.         p0[2] = r*sin(phi);
  667.  
  668.         p1[0] = cos(theta1)*(R + r*cos(phi));
  669.         p1[1] = -sin(theta1)*(R + r*cos(phi));
  670.         p1[2] = r*sin(phi);
  671.  
  672.         p2[0] = cos(theta1)*(R + r*cos(phi1));
  673.         p2[1] = -sin(theta1)*(R + r*cos(phi1));
  674.         p2[2] = r*sin(phi1);
  675.  
  676.         p3[0] = cos(theta)*(R + r*cos(phi1));
  677.         p3[1] = -sin(theta)*(R + r*cos(phi1));
  678.         p3[2] = r*sin(phi1);
  679.  
  680.         n0[0] = cos(theta)*(cos(phi));
  681.         n0[1] = -sin(theta)*(cos(phi));
  682.         n0[2] = sin(phi);
  683.  
  684.         n1[0] = cos(theta1)*(cos(phi));
  685.         n1[1] = -sin(theta1)*(cos(phi));
  686.         n1[2] = sin(phi);
  687.  
  688.         n2[0] = cos(theta1)*(cos(phi1));
  689.         n2[1] = -sin(theta1)*(cos(phi1));
  690.         n2[2] = sin(phi1);
  691.  
  692.         n3[0] = cos(theta)*(cos(phi1));
  693.         n3[1] = -sin(theta)*(cos(phi1));
  694.         n3[2] = sin(phi1);
  695.  
  696.         m_xformpt(p0, p0, n0, n0);
  697.         m_xformpt(p1, p1, n1, n1);
  698.         m_xformpt(p2, p2, n2, n2);
  699.         m_xformpt(p3, p3, n3, n3);
  700.  
  701.         glBegin(type);
  702.         glNormal3dv(n3);
  703.         glVertex3dv(p3);
  704.         glNormal3dv(n2);
  705.         glVertex3dv(p2);
  706.         glNormal3dv(n1);
  707.         glVertex3dv(p1);
  708.         glNormal3dv(n0);
  709.         glVertex3dv(p0);
  710.         glEnd();
  711.     }
  712.     }
  713. }
  714.  
  715. /* octahedron data: The octahedron produced is centered 
  716.  * at the origin and has radius 1.0 
  717.  */
  718. static GLdouble odata[6][3] = {
  719.   {1.0, 0.0, 0.0},
  720.   {-1.0, 0.0, 0.0},
  721.   {0.0, 1.0, 0.0},
  722.   {0.0, -1.0, 0.0},
  723.   {0.0, 0.0, 1.0},
  724.   {0.0, 0.0, -1.0}
  725. };
  726.  
  727. static int ondex[8][3] = {
  728.     {0, 4, 2}, {1, 2, 4}, {0, 3, 4}, {1, 4, 3},
  729.     {0, 2, 5}, {1, 5, 2}, {0, 5, 3}, {1, 3, 5}
  730. };
  731.  
  732. /* tetrahedron data: */
  733.  
  734. #define T    1.73205080756887729
  735.  
  736. static GLdouble tdata[4][3] = {
  737.     {T, T, T}, {T, -T, -T}, {-T, T, -T}, {-T, -T, T}
  738. };
  739.  
  740. static int tndex[4][3] = {
  741.     {0, 1, 3}, {2, 1, 0}, {3, 2, 0}, {1, 2, 3}
  742. };
  743.  
  744. /* icosahedron data: These numbers are rigged to 
  745.  * make an icosahedron of radius 1.0 
  746.  */
  747.  
  748. #define X .525731112119133606
  749. #define Z .850650808352039932
  750.  
  751. static GLdouble idata[12][3] = {
  752.   {-X, 0.0, Z},
  753.   {X, 0.0, Z},
  754.   {-X, 0.0, -Z},
  755.   {X, 0.0, -Z},
  756.   {0.0, Z, X},
  757.   {0.0, Z, -X},
  758.   {0.0, -Z, X},
  759.   {0.0, -Z, -X},
  760.   {Z, X, 0.0},
  761.   {-Z, X, 0.0},
  762.   {Z, -X, 0.0},
  763.   {-Z, -X, 0.0},
  764. };
  765.  
  766. static int iindex[20][3] = {
  767.     {0, 4, 1},    {0, 9, 4},
  768.     {9, 5, 4},    {4, 5, 8},
  769.     {4, 8, 1},    {8, 10, 1},
  770.     {8, 3, 10},    {5, 3, 8},
  771.     {5, 2, 3},    {2, 7, 3},
  772.     {7, 10, 3},    {7, 6, 10},
  773.     {7, 11, 6},    {11, 0, 6},
  774.     {0, 1, 6},    {6, 1, 10},
  775.     {9, 0, 11},    {9, 11, 2},
  776.     {9, 2, 5},    {7, 2, 11},
  777. };
  778.  
  779. /* icosahedron:
  780.  *
  781.  * Draws an icosahedron with center at p0 having the
  782.  * given radius.
  783.  */
  784.  
  785. static void icosahedron(GLdouble p0[3], GLdouble radius, GLenum shadeType)
  786. {
  787.     int i;
  788.  
  789.     for (i = 0; i < 20; i++)
  790.     drawtriangle(i, 0, 1, p0, radius, shadeType, 0);
  791. }
  792.  
  793. /* octahedron:
  794.  *
  795.  * Draws an octahedron with center at p0 having the
  796.  * given radius.
  797.  */
  798. static void octahedron(GLdouble p0[3], GLdouble radius, GLenum shadeType)
  799. {
  800.     int i;
  801.  
  802.     for (i = 0; i < 8; i++)
  803.     drawtriangle(i, 1, 1, p0, radius, shadeType, 0);
  804. }
  805.  
  806. /* tetrahedron:
  807.  *
  808.  * Draws an tetrahedron with center at p0 having the
  809.  * given radius.
  810.  */
  811.  
  812. static void tetrahedron(GLdouble p0[3], GLdouble radius, GLenum shadeType)
  813. {
  814.     int i;
  815.  
  816.     for (i = 0; i < 4; i++)
  817.     drawtriangle(i, 2, 1, p0, radius, shadeType, 0);
  818. }
  819.  
  820. static void subdivide(int depth, GLdouble *v0, GLdouble *v1, GLdouble *v2,
  821.     GLdouble p0[3], GLdouble radius, GLenum shadeType, int avnormal)
  822. {
  823.     GLdouble w0[3], w1[3], w2[3];
  824.     GLdouble l;
  825.     int i, j, k, n;
  826.  
  827.     for (i = 0; i < depth; i++)
  828.     for (j = 0; i + j < depth; j++) {
  829.         k = depth - i - j;
  830.         for (n = 0; n < 3; n++) {
  831.         w0[n] = (i*v0[n] + j*v1[n] + k*v2[n])/depth;
  832.         w1[n] = ((i+1)*v0[n] + j*v1[n] + (k-1)*v2[n])/depth;
  833.         w2[n] = (i*v0[n] + (j+1)*v1[n] + (k-1)*v2[n])/depth;
  834.         }
  835.         l = sqrt(w0[0]*w0[0] + w0[1]*w0[1] + w0[2]*w0[2]);
  836.         w0[0] /= l; w0[1] /= l; w0[2] /= l;
  837.         l = sqrt(w1[0]*w1[0] + w1[1]*w1[1] + w1[2]*w1[2]);
  838.         w1[0] /= l; w1[1] /= l; w1[2] /= l;
  839.         l = sqrt(w2[0]*w2[0] + w2[1]*w2[1] + w2[2]*w2[2]);
  840.         w2[0] /= l; w2[1] /= l; w2[2] /= l;
  841.         recorditem(w1, w0, w2, p0, radius, shadeType, avnormal);
  842.     }
  843.     for (i = 0; i < depth-1; i++)
  844.     for (j = 0; i + j < depth-1; j++) {
  845.         k = depth - i - j;
  846.         for (n = 0; n < 3; n++) {
  847.         w0[n] = ((i+1)*v0[n] + (j+1)*v1[n] + (k-2)*v2[n])/depth;
  848.         w1[n] = ((i+1)*v0[n] + j*v1[n] + (k-1)*v2[n])/depth;
  849.         w2[n] = (i*v0[n] + (j+1)*v1[n] + (k-1)*v2[n])/depth;
  850.         }
  851.         l = sqrt(w0[0]*w0[0] + w0[1]*w0[1] + w0[2]*w0[2]);
  852.         w0[0] /= l; w0[1] /= l; w0[2] /= l;
  853.         l = sqrt(w1[0]*w1[0] + w1[1]*w1[1] + w1[2]*w1[2]);
  854.         w1[0] /= l; w1[1] /= l; w1[2] /= l;
  855.         l = sqrt(w2[0]*w2[0] + w2[1]*w2[1] + w2[2]*w2[2]);
  856.         w2[0] /= l; w2[1] /= l; w2[2] /= l;
  857.         recorditem(w0, w1, w2, p0, radius, shadeType, avnormal);
  858.     }
  859. }
  860.  
  861. static void drawtriangle(int i, int geomType, int depth,
  862.     GLdouble p0[3], GLdouble radius, GLenum shadeType, int avnormal)
  863. {
  864.     GLdouble *x0, *x1, *x2;
  865.  
  866.     switch (geomType) {
  867.     case 0:    /* icosahedron */
  868.         x0 = &idata[iindex[i][0]][0];
  869.         x1 = &idata[iindex[i][1]][0];
  870.         x2 = &idata[iindex[i][2]][0];
  871.         break;
  872.     case 1: /* octahedron */
  873.         x0 = &odata[ondex[i][0]][0];
  874.         x1 = &odata[ondex[i][1]][0];
  875.         x2 = &odata[ondex[i][2]][0];
  876.         break;
  877.     case 2: /* tetrahedron */
  878.         x0 = &tdata[tndex[i][0]][0];
  879.         x1 = &tdata[tndex[i][1]][0];
  880.         x2 = &tdata[tndex[i][2]][0];
  881.         break;
  882.     }
  883.     subdivide(depth, x0, x1, x2, p0, radius, shadeType, avnormal);
  884. }
  885.  
  886. static void recorditem(GLdouble *n1, GLdouble *n2, GLdouble *n3,
  887.            GLdouble center[3], GLdouble radius, GLenum shadeType, int avnormal)
  888. {
  889.     GLdouble p1[3], p2[3], p3[3], q0[3], q1[3], n11[3], n22[3], n33[3];
  890.     int    i;
  891.  
  892.     for (i = 0; i < 3; i++) {
  893.     p1[i] = n1[i]*radius + center[i];
  894.     p2[i] = n2[i]*radius + center[i];
  895.     p3[i] = n3[i]*radius + center[i];
  896.     }
  897.     if (avnormal == 0) {
  898.     diff3(p1, p2, q0);
  899.     diff3(p2, p3, q1);
  900.     crossprod(q0, q1, q1);
  901.     normalize(q1);
  902.     m_xformpt(p1, p1, q1, n11);
  903.     m_xformptonly(p2, p2);
  904.     m_xformptonly(p3, p3);
  905.  
  906.     glBegin (shadeType);
  907.     glNormal3dv(n11);
  908.     glVertex3dv(p1);
  909.     glVertex3dv(p2);
  910.     glVertex3dv(p3);
  911.     glEnd();
  912.     return;
  913.     }
  914.     m_xformpt(p1, p1, n1, n11);
  915.     m_xformpt(p2, p2, n2, n22);
  916.     m_xformpt(p3, p3, n3, n33);
  917.  
  918.     glBegin (shadeType);
  919.     glNormal3dv(n11);
  920.     glVertex3dv(p1);
  921.     glNormal3dv(n22);
  922.     glVertex3dv(p2);
  923.     glNormal3dv(n33);
  924.     glVertex3dv(p3);
  925.     glEnd();
  926. }
  927.  
  928. static GLdouble dodec[20][3];
  929.  
  930. static void initdodec()
  931. {
  932.     GLdouble alpha, beta;
  933.  
  934.     alpha = sqrt(2.0/(3.0 + sqrt(5.0)));
  935.     beta = 1.0 + sqrt(6.0/(3.0 + sqrt(5.0)) - 2.0 + 2.0*sqrt(2.0/(3.0 +
  936.                                 sqrt(5.0))));
  937.     dodec[0][0] = -alpha; dodec[0][1] = 0; dodec[0][2] = beta;
  938.     dodec[1][0] = alpha; dodec[1][1] = 0; dodec[1][2] = beta;
  939.     dodec[2][0] = -1; dodec[2][1] = -1; dodec[2][2] = -1;
  940.     dodec[3][0] = -1; dodec[3][1] = -1; dodec[3][2] = 1;
  941.     dodec[4][0] = -1; dodec[4][1] = 1; dodec[4][2] = -1;
  942.     dodec[5][0] = -1; dodec[5][1] = 1; dodec[5][2] = 1;
  943.     dodec[6][0] = 1; dodec[6][1] = -1; dodec[6][2] = -1;
  944.     dodec[7][0] = 1; dodec[7][1] = -1; dodec[7][2] = 1;
  945.     dodec[8][0] = 1; dodec[8][1] = 1; dodec[8][2] = -1;
  946.     dodec[9][0] = 1; dodec[9][1] = 1; dodec[9][2] = 1;
  947.     dodec[10][0] = beta; dodec[10][1] = alpha; dodec[10][2] = 0;
  948.     dodec[11][0] = beta; dodec[11][1] = -alpha; dodec[11][2] = 0;
  949.     dodec[12][0] = -beta; dodec[12][1] = alpha; dodec[12][2] = 0;
  950.     dodec[13][0] = -beta; dodec[13][1] = -alpha; dodec[13][2] = 0;
  951.     dodec[14][0] = -alpha; dodec[14][1] = 0; dodec[14][2] = -beta;
  952.     dodec[15][0] = alpha; dodec[15][1] = 0; dodec[15][2] = -beta;
  953.     dodec[16][0] = 0; dodec[16][1] = beta; dodec[16][2] = alpha;
  954.     dodec[17][0] = 0; dodec[17][1] = beta; dodec[17][2] = -alpha;
  955.     dodec[18][0] = 0; dodec[18][1] = -beta; dodec[18][2] = alpha;
  956.     dodec[19][0] = 0; dodec[19][1] = -beta; dodec[19][2] = -alpha;
  957. }
  958.  
  959. /* dodecahedron:
  960.  *
  961.  * Draws an dodecahedron with center at 0.0. The radius
  962.  * is sqrt(3).
  963.  */
  964. static void dodecahedron(GLdouble center[3], GLdouble sc, GLenum type)
  965. {
  966.     static int inited = 0;
  967.  
  968.     if ( inited == 0) {
  969.     inited = 1;
  970.     initdodec();
  971.     }
  972.     m_pushmatrix();
  973.     m_translate(center[0], center[1], center[2]);
  974.     m_scale(sc, sc, sc);
  975.     pentagon(0, 1, 9, 16, 5, type);
  976.     pentagon(1, 0, 3, 18, 7, type);
  977.     pentagon(1, 7, 11, 10, 9, type);
  978.     pentagon(11, 7, 18, 19, 6, type);
  979.     pentagon(8, 17, 16, 9, 10, type);
  980.     pentagon(2, 14, 15, 6, 19, type);
  981.     pentagon(2, 13, 12, 4, 14, type);
  982.     pentagon(2, 19, 18, 3, 13, type);
  983.     pentagon(3, 0, 5, 12, 13, type);
  984.     pentagon(6, 15, 8, 10, 11, type);
  985.     pentagon(4, 17, 8, 15, 14, type);
  986.     pentagon(4, 12, 5, 16, 17, type);
  987.     m_popmatrix();
  988. }
  989.  
  990. static void pentagon(int a, int b, int c, int d, int e, GLenum shadeType)
  991. {
  992.     GLdouble n0[3], d1[3], d2[3], d3[3], d4[3], d5[3], nout[3];
  993.  
  994.     diff3(&dodec[a][0], &dodec[b][0], d1);
  995.     diff3(&dodec[b][0], &dodec[c][0], d2);
  996.     crossprod(d1, d2, n0);
  997.     normalize(n0);
  998.     m_xformpt(&dodec[a][0], d1, n0, nout);
  999.     m_xformptonly(&dodec[b][0], d2);
  1000.     m_xformptonly(&dodec[c][0], d3);
  1001.     m_xformptonly(&dodec[d][0], d4);
  1002.     m_xformptonly(&dodec[e][0], d5);
  1003.  
  1004.     glBegin (shadeType);
  1005.     glNormal3dv(nout);
  1006.     glVertex3dv(d1);
  1007.     glVertex3dv(d2);
  1008.     glVertex3dv(d3);
  1009.     glVertex3dv(d4);
  1010.     glVertex3dv(d5);
  1011.     glEnd();
  1012. }
  1013.  
  1014. /*    linked lists--display lists for each different 
  1015.  *    type of geometric objects.  The linked list is 
  1016.  *    searched, until an object of the requested
  1017.  *    size is found.  If no geometric object of that size
  1018.  *    has been previously made, a new one is created.
  1019.  */
  1020. GLuint findList (int lindex, GLdouble *paramArray, int size) 
  1021. {
  1022.     MODELPTR endList;
  1023.     int found = 0;
  1024.     
  1025.     endList = lists[lindex];
  1026.     while (endList != NULL) {
  1027.     if (compareParams (endList->params, paramArray, size))
  1028.         return (endList->list);
  1029.     endList = endList->ptr;
  1030.     }
  1031. /*  if not found, return 0 and calling routine should
  1032.  *  make a new list    
  1033.  */
  1034.     return (0);
  1035. }
  1036.  
  1037. int compareParams (GLdouble *oneArray, GLdouble *twoArray, int size) 
  1038. {
  1039.     int i;
  1040.     int matches = 1;
  1041.  
  1042.     for (i = 0; (i < size) && matches; i++) {
  1043.     if (*oneArray++ != *twoArray++)
  1044.         matches = 0;
  1045.     }
  1046.     return (matches);
  1047. }
  1048.  
  1049. GLuint makeModelPtr (int lindex, GLdouble *sizeArray, int count)
  1050. {
  1051.     MODELPTR newModel;
  1052.  
  1053.     newModel = (MODELPTR) malloc (sizeof (MODEL));
  1054.     newModel->list = glGenLists (1);
  1055.     newModel->numParam = count;
  1056.     newModel->params = sizeArray;
  1057.     newModel->ptr = lists[lindex];
  1058.     lists[lindex] = newModel;
  1059.  
  1060.     return (newModel->list);
  1061. }
  1062.